<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <title>狮子座</title>
  <link rel="icon" href="https://img.kaikeba.com/kkb_portal_icon.ico">
  <style>
    body {
      margin: 0;
      overflow: hidden;
    }

    #canvas {
      background: url("./images/sky.jpg");
      background-size: cover;
      background-position: right bottom;
    }

    #audio {
      position: absolute;
      right: 20px;
      bottom: 20px;
      opacity: 10%;
      transition: opacity 200ms;
      z-index: 20;
    }

    #audio:hover {
      opacity: 90%;
    }
  </style>
</head>

<body>
  <canvas id="canvas"></canvas>
  <audio id="audio" controls loop autoplay>
    <source src="./audio/szz.mp3" type="audio/mpeg" />
  </audio>
  <!-- 顶点着色器 -->
  <script id="vertexShader" type="x-shader/x-vertex">
      attribute vec4 a_Attr;
      varying float v_Alpha;
      void main(){
          gl_Position=vec4(a_Attr.x,a_Attr.y,0.0,1.0);
          gl_PointSize=a_Attr.z;
          v_Alpha=a_Attr.w;
      }
    </script>
  <!-- 片元着色器 -->
  <script id="fragmentShader" type="x-shader/x-fragment">
    precision mediump float;    
    uniform bool u_IsPOINTS;
    varying float v_Alpha;
    void main(){ 
      if(u_IsPOINTS){
        float dist=distance(gl_PointCoord,vec2(0.5,0.5));
        if(dist<0.5){
          gl_FragColor=vec4(0.87,0.91,1,v_Alpha);
        }else{
          discard;
        }
      }else{
        gl_FragColor=vec4(0.87,0.91,1,v_Alpha);
      }
    }  
  </script>
  <script type="module">
    import { initShaders, getMousePosInWebgl, glToCssPos } from "../jsm/Utils.js";
    import Poly from '../jsm/Poly.js';
    import Sky from '../jsm/Sky.js';
    import Compose from '../jsm/Compose.js';
    import Track from '../jsm/Track.js';

    const canvas = document.querySelector("#canvas");
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;

    // 获取着色器文本
    const vsSource = document.querySelector("#vertexShader").innerText;
    const fsSource = document.querySelector("#fragmentShader").innerText;

    //三维画笔
    const gl = canvas.getContext("webgl");
    gl.enable(gl.BLEND);
    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);

    //初始化着色器
    initShaders(gl, vsSource, fsSource);


    //声明颜色 rgba
    gl.clearColor(0, 0, 0, 0);
    //刷底色
    gl.clear(gl.COLOR_BUFFER_BIT);

    //夜空
    const sky = new Sky(gl)
    //建立合成对象
    const compose = new Compose()

    //正在绘制的多边形
    let poly = null
    //鼠标划上的点
    let point = null

    //取消右击提示
    canvas.oncontextmenu = function () {
      return false
    }

    canvas.addEventListener('mousedown', (event) => {
      if (event.button === 2) {
        popVertice()
      } else {
        const { x, y } = getMousePosInWebgl(event, canvas)
        if (poly) {
          addVertice(x, y)
        } else {
          crtPoly(x, y)
        }
      }
      render()
    })

    canvas.addEventListener('mousemove', (event) => {
      const { x, y } = getMousePosInWebgl(event, canvas)
      point = hoverPoint(x, y)
      canvas.style.cursor = point ? 'pointer' : 'default'
      if (poly) {
        const obj = poly.geoData[poly.geoData.length - 1]
        obj.x = x
        obj.y = y
      }
    })

    !(function ani() {
      compose.update(new Date())
      sky.updateVertices(['x', 'y', 'pointSize', 'alpha'])
      render()
      requestAnimationFrame(ani)
    })()

    function crtPoly(x, y) {
      let o1 = point ? point : { x, y, pointSize: random(), alpha: 1 }
      const o2 = { x, y, pointSize: random(), alpha: 1 }
      poly = new Poly({
        size: 4,
        attrName: 'a_Attr',
        geoData: [o1, o2],
        types: ['POINTS', 'LINE_STRIP'],
        circleDot: true
      })
      sky.add(poly)
      crtTrack(o1)
      crtTrack(o2)
    }

    function addVertice(x, y) {
      const { geoData } = poly
      if (point) {
        geoData[geoData.length - 1] = point
      }
      let obj = { x, y, pointSize: random(), alpha: 1 }
      geoData.push(obj)
      crtTrack(obj)
    }

    function popVertice() {
      poly.geoData.pop()
      const { children } = compose
      const last = children[children.length - 1]
      children.delete(last)
      poly = null
    }

    function crtTrack(obj) {
      const { pointSize } = obj
      const track = new Track(obj)
      track.start = new Date()
      track.timeLen = 2000
      track.loop = true
      track.keyMap = new Map([
        [
          "pointSize",
          [
            [500, pointSize],
            [1000, 0],
            [1500, pointSize],
          ],
        ],
        [
          "alpha",
          [
            [500, 1],
            [1000, 0],
            [1500, 1],
          ],
        ],
      ]);
      compose.add(track)
    }

    function hoverPoint(mx, my) {
      for (let { geoData } of sky.children) {
        for (let obj of geoData) {
          if (poly && obj === poly.geoData[poly.geoData.length - 1]) {
            continue
          }
          const delta = {
            x: mx - obj.x,
            y: my - obj.y
          }
          const { x, y } = glToCssPos(delta, canvas)
          const dist = x * x + y * y
          if (dist < 100) {
            return obj
          }
        }
      }
      return null
    }

    function random() {
      return Math.random() * 8 + 3
    }

    function render() {
      gl.clear(gl.COLOR_BUFFER_BIT);
      sky.draw()
    }

  </script>
</body>

</html>